#include "stdafx.h"
#include "SimSplicedRead.h"
#include <time.h>

SimSplicedRead::SimSplicedRead(const char* fileName)
{
    ofile.open(fileName);
    this->bFastaFormat = true;
    if (hasTheExtName(fileName, ".fq") || hasTheExtName(fileName, ".fastq")) {
        this->bFastaFormat = false;
    }
}

SimSplicedRead::~SimSplicedRead(void)
{
    ofile.close();
}

inline int readMiddleL(int readL, int anchorL)
{
    if (readL > 2 * anchorL) {
        return(readL - 2 * anchorL);
    }
    return(0);
}

bool SimSplicedRead::setSimPtr(int readLength, int anchorLength, bool bFastaFormat)
{
    this->noSimRead = 0;
    this->readLength = min(readLength, MAX_LINE - 1);
    this->anchorLength = anchorLength;
    this->middleLength = readMiddleL(this->readLength, this->anchorLength);
    if (this->middleLength <= 0) {
        cout << "The read is too short to be simulated and be mapped" << endl;
        return(false);
    }
    return(true);
}

int printSimRead(ofstream& ofile, const char* readName, char* caBuf, bool bFasta)
{
    if (bFasta) {
        ofile << '>' << readName << '\n';
        ofile << caBuf << endl;
    } else { // fastq
        ofile << '@' << readName << '\n';
        ofile << caBuf << endl;
        ofile << '+' << endl;
        for (int i = 0; caBuf[i] != '\0'; caBuf[i++] = 'I'); // make fake quality scores
        ofile << caBuf << endl;
    }
    return(0);
}

int SimSplicedRead::simulateASplicedRead(const char* ref, const char* refN,\
        int splicedPos, int sep, int start, bool revComp)
{
    char caBuf[MAX_LINE];
    int j;
    // Simulate reads in the left arm.
    for (j = 0; j < splicedPos; j++) {
        char c = ref[start + j];
        if ( isACGT(c) || c == 'N') {
            caBuf[j] = c;
        } else {
            return(this->noSimRead);
        }
    }
    // Simulate reads in the right arm.
    for (; j < readLength; j++) {
        char c = ref[start + j + sep];
        if ( isACGT(c) || c == 'N') {
            caBuf[j] = c;
        } else {
            return(this->noSimRead);
        }
    }
    caBuf[j] = '\0';
    char strand = '+';
    if (revComp) {
        strand = '-';
        reverseComplementKmer(caBuf);
    }
    char readN[MAX_LINE];
    sprintf(readN, "%d%c%d_%d", this->noSimRead + 1, strand, splicedPos, sep);
    printSimRead(this->ofile, readN, caBuf, this->bFastaFormat);
    this->noSimRead ++;
    return(0);
}

int SimSplicedRead::simulateReads(const char* ref, const char* refN,\
                                  int start, int simNo)
{
    const int sep = 300;
    int strLength = (int)strlen(ref);
    srand((unsigned int) time(NULL) );
    for (int i = start; i < start + simNo; i++) {
        if (i + sep + this->readLength >= strLength) {
            // cout << "End of the reference " << endl;
            break;
        }
        bool revComp = (i % 2 == 0);
        int leftL = min(this->anchorLength + rand() % this->middleLength, this->readLength);
        simulateASplicedRead(ref, refN, leftL, sep, start + i, revComp);
    }
    return(this->noSimRead);
}